The Runtime Environment
The runtime model for the execution of part editors in the OpenDoc environ-
ment is different from that of conventional applications. This section discusses those differences in terms of the runtime process model, System Object Model runtime issues, and the part wrapper object. It also discusses name spaces, a runtime service provided by OpenDoc.The OpenDoc Runtime Process
The OpenDoc document-centered approach requires a runtime process model significantly different from the classic application-centered process model. On personal-computer platforms, each process is usually owned by an application. This process provides the address space in which the application code executes as well as the memory for every document opened by that application. The operating system assigns a document to a process based on the document's type, an indication of which application created it.In OpenDoc, a document no longer has a single type but is instead composed of many parts that may be of different types. Thus, the document, not any application, is the owner of the process. The document manages standard tasks such as handling the event loop, managing files, printing, and interacting with system menus, dialog boxes, and so on. In OpenDoc, some of this behavior is provided by a shared library called the document shell. The fact that individual parts in a document share this code is one reason why part editors can be significantly smaller than conventional applications.
The document shell has the following basic responsibilities:
The executable code of part editors is stored and accessed as shared libraries, independent of any process. (Note that part-editor code must be reentrant on the Mac OS because several instances of a part in a single document may use the same editor.) What the process provides is an address space for the contents of a particular document, along with any additional memory needed by the individual part editors. All state information used by any part editor is, with some minor exceptions, maintained in the processes of those documents that contain parts manipulated by the editor.
- It creates and initializes the session object, which in turn creates and initializes the other session-wide OpenDoc objects, as shown in Figure 11-4.
- It opens the document chosen by the user.
- It accepts events and passes them to the OpenDoc dispatcher.
- It handles certain document-wide menu commands.
- Multiprocess runtime model
- The single-process-per-document model is not the only runtime model possible with OpenDoc. On platforms that provide fast process switching and efficient interprocess dispatch, the document shell process can run each part in a separate process.
![]()
CFM and the System Object Model
Two cornerstones of the OpenDoc runtime environment are dynamic linking, which allows compound documents to be assembled at runtime, and a language-neutral object model, which facilitates runtime compatibility of parts and minimizes the recompilation required by changes to OpenDoc or to part editors.Dynamic linking on the Mac OS platform is provided by the Code Fragment Manager (CFM). The object model used by OpenDoc is the System Object Model (SOM). This section introduces some runtime aspects of CFM and SOM that are of interest to part-editor developers. (The particulars of writing SOM-based code are discussed in the section "Developing With SOMobjects and IDL".) For more information, see the SOM appendix of the OpenDoc Cookbook for the Mac OS.
Dynamic Linking
OpenDoc depends on dynamic linking to allow the appropriate executable code to be added to the runtime environment of a document. Before a document is opened, there is no way of knowing what part editors may be needed to manipulate its contents. The dynamic linking used by OpenDoc on the Mac OS relies on the Code Fragment Manager (CFM) to manipulate code fragments. The dynamic linking provided by CFM has the following capabilities:
- It allows an executable module to be loaded into memory once and then shared by multiple processes.
- It allows dynamically linked code to call code contained in another dynamically linked library.
- It gives dynamically linked code access to global variables.
SOM and Distributed Dispatching
System Object Model (SOM) objects are CORBA-compliant, meaning that
they follow the language-neutral distributed standards of the Common
Object Request Broker Architecture (CORBA), established by the Object Management Group (OMG), an industry consortium. Compliance with
these standards mean that objects compiled in different languages or with different compilers can communicate with each other.More than that, SOM objects running on different machines can communicate with each other. This distributed dispatching may be a future capability of OpenDoc and is therefore supported in these basic architectural features:
- Almost all objects are instantiated by factory objects rather than by constructors called by your part. See Table 11-1 for a list of the factory objects.
- The OpenDoc support for scripting is designed to allow for remote callback functions; see "Scripting-Related OpenDoc Classes".
- To enhance performance, OpenDoc minimizes the frequency of interpart and interlibrary method calls, except in cases--such as layout support--where frequent calls cannot be avoided.
SOM Exception Handling
OpenDoc objects are SOM objects, and as such they follow the CORBA rules for handling exceptions. Every method call made to an OpenDoc object (including your part, as a subclass ofODPart
) must therefore include an environment parameter (ev
), a pointer to a value that can describe an error. For example, theCreateLinkSource
method ofODDraft
has the following prototype (in IDL):
ODLinkSource CreateLinkSource(in ODPart part);The method takes a single parameter, of typeODPart
. To use this method, however, a caller in C++ must supply two parameters:
MyLinkSource = MyDraft->CreateLinkSource(ev, somSelf);If execution of the method results in an error condition, the receiver of the call (the draft object in this case) must place an exception code in the value pointed to byev
and return. The caller must therefore examine theev
parameter after every call to a SOM object to see if an exception has been raised.All OpenDoc methods that you call, as well as all public methods of your part editor that you write, must return errors this way. These are the implications for your exception handling:
The environment variable is passed along through a sequence of calls and can be used in calls to both SOM and C++ objects. Here is how you can use it correctly:
- You must supply an environment variable with all method calls to OpenDoc objects.
- You must check the environment variable after the call returns.
For more information on the environment parameter and exceptions, see SOMObjects Developer Toolkit Users Guide and SOMObjects Developer Toolkit Programmers Reference Manual from IBM.
- If your SOM method calls another SOM method, it can simply pass on the environment parameter it has received. This is the usual case, since your part editor executes only in response to calls to its SOM interface, and thus should always have received a value for the environment variable.
- If your SOM method calls a C++ method that may in turn call a SOM method, your SOM method can pass the environment parameter on to the C++ method (if the C++ method was designed to accept it; see next bullet).
- If your C++ method is called by a SOM method and in turn makes calls to SOM methods, it is best to design it to accept an environment parameter that it can then pass on.
- If your C++ method does not itself receive an environment parameter but it does call a SOM method, it can use a function provided by SOM (
somGetGlobalEnvironment
) to obtain a value for the environment variable.
Any exception-handling scheme that you use must support this method of passing exceptions. An OpenDoc utility library (Except), described in the OpenDoc Cookbook for the Mac OS, helps you check the environment variable after each method call.
The Part-Wrapper Object
Your part first initializes itself when OpenDoc calls itsInitPart
orInitPartFromStorage
method, as described in "Initializing and Reading a Part From Storage"partWrapper
parameter ofInitPart
orInitPartFromStorage
. That reference is to a part-wrapper object, a private object that OpenDoc creates and uses to represent your part.The part wrapper keeps other parts of OpenDoc from having direct pointers to your part object; its only function is to delegate methods of
ODPart
to your part. Using a part wrapper gives OpenDoc more flexibility in manipulating parts. For example, use of a part wrapper allows OpenDoc to switch editors for a part without having to close and reopen the part's document.You must use your part-wrapper reference in all calls to the OpenDoc interface that require you to pass a reference to yourself--for example, when registering your part for idle time. (Typically, if your part object keeps a field such as
fSelf
to hold a reference to itself, that field should contain the part-wrapper reference.) Specifically, you should never passsomSelf
as a parameter to any OpenDoc method except when accessing objects such as extensions and embedded-frame iterators for which your part itself is the factory.
- Part-wrapper methods
- The interface to
ODPart
includes three part-wrapper methods--IsRealPart
,GetRealPart
, andReleaseRealPart
--that are intended for the part-wrapper object only. OpenDoc calls these methods when associating your part with or disassociating it from its part wrapper. When you subclassODPart
to create your part editor, do not override these methods.![]()
Name Spaces
Each OpenDoc session provides a runtime service allowing you to define name spaces. A name space is an object that maps data types to values. It consists of a set of string-value pairs that associate the string (an ISO string) with the value (a 4-byte unsigned value, which could be a pointer to code).For example, OpenDoc uses name spaces to represent the preferences of the user for binding parts (whose part kinds are represented by ISO strings) to part editors (represented by pointers to editor IDs).
Name spaces are a general-purpose runtime registry mechanism. You can use them to define global spaces in which to share information with other parts. You can define as many name spaces as you wish; the OpenDoc name-space manager keeps a list (which is itself a name space) of all currently defined name spaces.
For example, you can use a name space to create palettes or other controls to be shared among several parts. Use an ISO string to identify the name space itself and ISO strings to identify each of the controls it encompasses. You then can get pointers to the controls (if the name space has already been instantiated) or instantiate the name space and provide pointers to the controls (if your part is the first in the session to use the name space).
If you publish the ISO strings that define your name space and its contents, the name space can be used publicly. If you do not publish the names, you can still use the name space for your own private global variables.
Main | Page One | What's New | Apple Computer, Inc. | Find It | Contact Us | Help